home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Tutorials / Tut05_Send / Send.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  21KB  |  652 lines

  1. //----------------------------------------------------------------------------
  2. // File: Send.cpp
  3. //
  4. // Desc: This simple program builds upon the last tutorial and adds a send
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corp. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define INITGUID
  9. #define _WIN32_DCOM
  10. #include <stdio.h>
  11. #include <dplay8.h>
  12.  
  13.  
  14.  
  15. //-----------------------------------------------------------------------------
  16. // App specific structures 
  17. //-----------------------------------------------------------------------------
  18. struct HOST_NODE
  19. {
  20.     DPN_APPLICATION_DESC*   pAppDesc;
  21.     IDirectPlay8Address*    pHostAddress;
  22.     WCHAR*                  pwszSessionName;
  23.  
  24.     HOST_NODE*              pNext;
  25. };
  26.  
  27.  
  28. //-----------------------------------------------------------------------------
  29. // Global variables
  30. //-----------------------------------------------------------------------------
  31. IDirectPlay8Peer*                   g_pDP               = NULL;
  32. IDirectPlay8Address*                g_pDeviceAddress    = NULL;
  33. IDirectPlay8Address*                g_pHostAddress      = NULL;
  34. BOOL                                g_bHost;
  35. HOST_NODE*                          g_pHostList         = NULL;
  36. CRITICAL_SECTION                    g_csHostList;
  37.  
  38.  
  39. // This GUID allows DirectPlay to find other instances of the same game on
  40. // the network.  So it must be unique for every game, and the same for 
  41. // every instance of that game.  // {590E16DD-538F-40fb-A7DF-9654EA6BE71E}
  42. GUID g_guidApp = { 0x590e16dd, 0x538f, 0x40fb, { 0xa7, 0xdf, 0x96, 0x54, 0xea, 0x6b, 0xe7, 0x1e } };
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Function-prototypes
  47. //-----------------------------------------------------------------------------
  48. HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);
  49. BOOL    IsServiceProviderValid(const GUID* pGuidSP);
  50. HRESULT InitDirectPlay();
  51. HRESULT CreateDeviceAddress();
  52. HRESULT CreateHostAddress(WCHAR* pwszHost);
  53. HRESULT HostSession();
  54. HRESULT EnumDirectPlayHosts();
  55. HRESULT ConnectToSession();
  56. HRESULT SendDirectPlayMessage();
  57. void    CleanupDirectPlay();
  58.  
  59.  
  60. //-----------------------------------------------------------------------------
  61. // Miscellaneous helper functions
  62. //-----------------------------------------------------------------------------
  63. #define SAFE_DELETE(p)          {if(p) {delete (p);     (p)=NULL;}}
  64. #define SAFE_DELETE_ARRAY(p)    {if(p) {delete[] (p);   (p)=NULL;}}
  65. #define SAFE_RELEASE(p)         {if(p) {(p)->Release(); (p)=NULL;}}
  66.  
  67. #define USER_HOST       1
  68. #define USER_CONNECT    2
  69. #define USER_EXIT       1
  70. #define USER_SEND       2
  71.  
  72.  
  73.  
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Name: main()
  77. // Desc: Entry point for the application.  
  78. //-----------------------------------------------------------------------------
  79. int main(int argc, char* argv[], char* envp[])
  80. {
  81.     HRESULT hr;
  82.     int     iUserChoice;
  83.  
  84.     // Init COM so we can use CoCreateInstance
  85.     CoInitializeEx(NULL, COINIT_MULTITHREADED);
  86.  
  87.     // Init the DirectPlay system
  88.     if( FAILED( hr = InitDirectPlay() ) )
  89.     {
  90.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  91.         goto LCleanup;
  92.     }
  93.  
  94.     InitializeCriticalSection(&g_csHostList);
  95.  
  96.     // Get the necessary user input on whether they are hosting or connecting
  97.     do
  98.     {
  99.         printf("Please select one.\n1.  Host\n2.  Connect\n");
  100.         scanf("%d", &iUserChoice);
  101.     } while (iUserChoice != USER_HOST && iUserChoice != USER_CONNECT);
  102.  
  103.  
  104.     if( FAILED( hr = CreateDeviceAddress() ) )
  105.     {
  106.         printf("Failed CreatingDeviceAddress:  0x%X\n", hr);
  107.         goto LCleanup;
  108.     }
  109.  
  110.     if( iUserChoice == USER_HOST)
  111.     {
  112.         if( FAILED( hr = HostSession() ) )
  113.         {
  114.             printf("Failed Hosting:  0x%X\n", hr);
  115.             goto LCleanup;
  116.         }
  117.     }
  118.     else
  119.     {
  120.         if( FAILED( hr = EnumDirectPlayHosts() ) )
  121.         {
  122.             printf("Failed Enumerating Host:  0x%X\n", hr);
  123.             goto LCleanup;
  124.         }
  125.  
  126.         if( FAILED( hr = ConnectToSession() ) )
  127.         {
  128.             printf("Failed Connect to Host:  0x%X\n", hr);
  129.             goto LCleanup;
  130.         }
  131.         else
  132.         {
  133.             printf("\nConnection Successful.\n");
  134.         }
  135.     }
  136.  
  137.     // Present User with Choices
  138.     do
  139.     {
  140.         printf("Please select one.\n1.  Exit\n2.  Send Data\n");
  141.         scanf("%d", &iUserChoice);
  142.  
  143.         if( iUserChoice == USER_SEND)
  144.         {
  145.             if( FAILED( hr = SendDirectPlayMessage() ) )
  146.             {
  147.                 printf("Failed To Send Data:  0x%X\n", hr);
  148.                 goto LCleanup;
  149.             }
  150.         }
  151.     } while (iUserChoice != USER_EXIT);
  152.     
  153. LCleanup:
  154.     CleanupDirectPlay();
  155.  
  156.     // Cleanup COM
  157.     CoUninitialize();
  158.  
  159.     return 0;
  160. }
  161.  
  162.  
  163.  
  164.  
  165. //-----------------------------------------------------------------------------
  166. // Name: InitDirectPlay()
  167. // Desc: Initialize DirectPlay
  168. //-----------------------------------------------------------------------------
  169. HRESULT InitDirectPlay()
  170. {
  171.     HRESULT     hr = S_OK;
  172.  
  173.     // Create the IDirectPlay8Peer Object
  174.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8Peer, NULL, 
  175.                                     CLSCTX_INPROC_SERVER,
  176.                                     IID_IDirectPlay8Peer, 
  177.                                     (LPVOID*) &g_pDP ) ) )
  178.     {
  179.         printf("Failed Creating the IDirectPlay8Peer Object:  0x%X\n", hr);
  180.         goto LCleanup;
  181.     }
  182.  
  183.     // Init DirectPlay
  184.     if( FAILED( hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
  185.     {
  186.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  187.         goto LCleanup;
  188.     }
  189.     
  190.     // Ensure that TCP/IP is a valid Service Provider
  191.     if( FALSE == IsServiceProviderValid(&CLSID_DP8SP_TCPIP ) )
  192.     {
  193.         hr = E_FAIL;
  194.         printf("Failed validating CLSID_DP8SP_TCPIP");
  195.         goto LCleanup;
  196.     }
  197.  
  198. LCleanup:
  199.     return hr;
  200. }
  201.  
  202.  
  203.  
  204.  
  205. //-----------------------------------------------------------------------------
  206. // Name: IsServiceProviderValid()
  207. // Desc: Return TRUE if the service provider is valid
  208. //-----------------------------------------------------------------------------
  209. BOOL IsServiceProviderValid(const GUID* pGuidSP)
  210. {
  211.     HRESULT                     hr;
  212.     DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo = NULL;
  213.     DWORD                       dwItems = 0;
  214.     DWORD                       dwSize = 0;
  215.  
  216.     hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, NULL, &dwSize, &dwItems, 0);
  217.  
  218.     if( hr != DPNERR_BUFFERTOOSMALL)
  219.     {
  220.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  221.         goto LCleanup;
  222.     }
  223.  
  224.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  225.  
  226.     if( FAILED( hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ) ) )
  227.     {
  228.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  229.         goto LCleanup;
  230.     }
  231.  
  232.     // There are no items returned so the requested SP is not available
  233.     if( dwItems == 0)
  234.     {
  235.         hr = E_FAIL;
  236.     }
  237.  
  238. LCleanup:
  239.     SAFE_DELETE_ARRAY(pdnSPInfo);
  240.  
  241.     if( SUCCEEDED(hr) )
  242.         return TRUE;
  243.     else
  244.         return FALSE;
  245. }
  246.  
  247.  
  248.  
  249.  
  250. //-----------------------------------------------------------------------------
  251. // Name: DirectPlayMessageHandler
  252. // Desc: Handler for DirectPlay messages.  
  253. //-----------------------------------------------------------------------------
  254. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, 
  255.                                          PVOID pMsgBuffer)
  256. {
  257.     HRESULT     hr = S_OK;
  258.  
  259.     switch (dwMessageId)
  260.     {
  261.         case DPN_MSGID_ENUM_HOSTS_RESPONSE:
  262.         {
  263.             PDPNMSG_ENUM_HOSTS_RESPONSE     pEnumHostsResponseMsg;
  264.             const DPN_APPLICATION_DESC*     pAppDesc;
  265.             HOST_NODE*                      pHostNode = NULL;
  266.             WCHAR*                          pwszSession = NULL;
  267.  
  268.             pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE) pMsgBuffer;
  269.             pAppDesc = pEnumHostsResponseMsg->pApplicationDescription;
  270.  
  271.             // Insert each host response if it isn't already present
  272.             EnterCriticalSection(&g_csHostList);
  273.  
  274.             for (pHostNode = g_pHostList; pHostNode; pHostNode = pHostNode->pNext)
  275.             {
  276.                 if( pAppDesc->guidInstance == pHostNode->pAppDesc->guidInstance)
  277.                 {
  278.                     // This host is already in the list
  279.                     pHostNode = NULL;
  280.                     goto Break_ENUM_HOSTS_RESPONSE;
  281.                 }
  282.             }
  283.  
  284.             // This host session is not in the list then so insert it.
  285.             pHostNode = new HOST_NODE;
  286.             if( pHostNode == NULL)
  287.             {
  288.                 goto Break_ENUM_HOSTS_RESPONSE;
  289.             }
  290.  
  291.             ZeroMemory(pHostNode, sizeof(HOST_NODE));
  292.  
  293.             // Copy the Host Address
  294.             if( FAILED( pEnumHostsResponseMsg->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ) )
  295.             {
  296.                 goto Break_ENUM_HOSTS_RESPONSE;
  297.             }
  298.  
  299.             pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
  300.  
  301.             if( pHostNode == NULL)
  302.             {
  303.                 goto Break_ENUM_HOSTS_RESPONSE;
  304.             }
  305.  
  306.             ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
  307.             memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
  308.  
  309.             // Null out all the pointers we aren't copying
  310.             pHostNode->pAppDesc->pwszSessionName = NULL;
  311.             pHostNode->pAppDesc->pwszPassword = NULL;
  312.             pHostNode->pAppDesc->pvReservedData = NULL;
  313.             pHostNode->pAppDesc->dwReservedDataSize = 0;
  314.             pHostNode->pAppDesc->pvApplicationReservedData = NULL;
  315.             pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
  316.             
  317.             if( pAppDesc->pwszSessionName)
  318.             {
  319.                 pwszSession = new WCHAR[wcslen(pAppDesc->pwszSessionName) + 1];
  320.                 
  321.                 if( pwszSession)
  322.                 {
  323.                     wcscpy(pwszSession, pAppDesc->pwszSessionName);
  324.                 }
  325.             }
  326.  
  327.             pHostNode->pwszSessionName = pwszSession;
  328.  
  329.             // Insert it onto the front of the list
  330.             pHostNode->pNext = g_pHostList ? g_pHostList->pNext : NULL;
  331.             g_pHostList = pHostNode;
  332.             pHostNode = NULL;
  333.  
  334. Break_ENUM_HOSTS_RESPONSE:
  335.             LeaveCriticalSection(&g_csHostList);
  336.  
  337.             if( pHostNode)
  338.             {
  339.                 SAFE_RELEASE(pHostNode->pHostAddress);
  340.  
  341.                 SAFE_DELETE(pHostNode->pAppDesc);
  342.  
  343.                 delete pHostNode;
  344.             }
  345.  
  346.             break;
  347.         }
  348.  
  349.         case DPN_MSGID_RECEIVE:
  350.         {
  351.             PDPNMSG_RECEIVE     pMsg;
  352.  
  353.             pMsg = (PDPNMSG_RECEIVE) pMsgBuffer;
  354.  
  355.             printf("\nReceived Message:  %S\n", (WCHAR*)pMsg->pReceiveData);
  356.             break;
  357.         }
  358.     }
  359.     return hr;
  360. }
  361.  
  362.  
  363.  
  364.  
  365. //-----------------------------------------------------------------------------
  366. // Name: EnumDirectPlayHosts()
  367. // Desc: Enumerates the hosts
  368. //-----------------------------------------------------------------------------
  369. HRESULT EnumDirectPlayHosts()
  370. {
  371.     HRESULT                 hr = S_OK;
  372.     WCHAR                   wszHost[128];
  373.     DPN_APPLICATION_DESC    dpAppDesc;
  374.     WCHAR*                  pwszURL = NULL;
  375.  
  376.     // Prompt for the hostname/ip
  377.     printf("\nPlease enter the IP address of host:\n");
  378.     wscanf(L"%ls", wszHost);
  379.  
  380.     if( FAILED( hr = CreateHostAddress(wszHost ) ) )
  381.     {
  382.         printf("Failed Creating Host Address:  0x%X\n", hr);
  383.         goto LCleanup;
  384.     }
  385.  
  386.     // Now set up the Application Description
  387.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  388.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  389.     dpAppDesc.guidApplication = g_guidApp;
  390.  
  391.     // We now have the host address so lets enum
  392.     if( FAILED( hr = g_pDP->EnumHosts( &dpAppDesc,         // pApplicationDesc
  393.                                        g_pHostAddress,     // pdpaddrHost
  394.                                        g_pDeviceAddress,   // pdpaddrDeviceInfo
  395.                                        NULL, 0,            // pvUserEnumData, size
  396.                                        4,                  // dwEnumCount
  397.                                        0,                  // dwRetryInterval
  398.                                        0,                  // dwTimeOut
  399.                                        NULL,               // pvUserContext
  400.                                        NULL,               // pAsyncHandle
  401.                                        DPNENUMHOSTS_SYNC ) ) )// dwFlags
  402.     {
  403.         printf("Failed Enumerating the Hosts:  0x%X\n", hr);
  404.         goto LCleanup;
  405.     }
  406.  
  407. LCleanup:
  408.     return hr;
  409. }
  410.  
  411.  
  412.  
  413.  
  414. //-----------------------------------------------------------------------------
  415. // Name: CreateDeviceAddress()
  416. // Desc: Creates a device address
  417. //-----------------------------------------------------------------------------
  418. HRESULT CreateDeviceAddress()
  419. {
  420.     HRESULT         hr = S_OK;
  421.  
  422.     // Create our IDirectPlay8Address Device Address
  423.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  424.                                        CLSCTX_INPROC_SERVER,
  425.                                        IID_IDirectPlay8Address,
  426.                                        (LPVOID*) &g_pDeviceAddress ) ) )
  427.     {
  428.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  429.         goto LCleanup;
  430.     }
  431.     
  432.     // Set the SP for our Device Address
  433.     if( FAILED( hr = g_pDeviceAddress->SetSP(&CLSID_DP8SP_TCPIP ) ) )
  434.     {
  435.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  436.         goto LCleanup;
  437.     }
  438.  
  439. LCleanup:
  440.     return hr;
  441. }
  442.  
  443.  
  444.  
  445.  
  446. //-----------------------------------------------------------------------------
  447. // Name: CreateHostAddress()
  448. // Desc: Creates a host address
  449. //-----------------------------------------------------------------------------
  450. HRESULT CreateHostAddress(WCHAR* pwszHost)
  451. {
  452.     HRESULT         hr = S_OK;
  453.  
  454.     // Create our IDirectPlay8Address Host Address
  455.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  456.                                        CLSCTX_INPROC_SERVER,
  457.                                        IID_IDirectPlay8Address,
  458.                                        (LPVOID*) &g_pHostAddress ) ) )
  459.     {
  460.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  461.         goto LCleanup;
  462.     }
  463.     
  464.     // Set the SP for our Host Address
  465.     if( FAILED( hr = g_pHostAddress->SetSP( &CLSID_DP8SP_TCPIP ) ) )
  466.     {
  467.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  468.         goto LCleanup;
  469.     }
  470.  
  471.     // Set the hostname into the address
  472.     if( FAILED( hr = g_pHostAddress->AddComponent( DPNA_KEY_HOSTNAME, pwszHost,
  473.                                                    2*(wcslen(pwszHost) + 1), /*bytes*/
  474.                                                    DPNA_DATATYPE_STRING ) ) )
  475.     {
  476.         printf("Failed Adding Hostname to Host Address:  0x%X\n", hr);
  477.         goto LCleanup;
  478.     }
  479.  
  480. LCleanup:
  481.     return hr;
  482. }
  483.  
  484.  
  485.  
  486.  
  487. //-----------------------------------------------------------------------------
  488. // Name: HostSession()
  489. // Desc: Host a DirectPlay session
  490. //-----------------------------------------------------------------------------
  491. HRESULT HostSession()
  492. {
  493.     HRESULT                 hr = S_OK;
  494.     DPN_APPLICATION_DESC    dpAppDesc;
  495.     WCHAR                   wszSession[128];
  496.  
  497.  
  498.     // Prompt the user for the session name
  499.     printf("\nPlease Enter a Session Name.\n");
  500.     wscanf(L"%ls", wszSession);
  501.  
  502.     // Now set up the Application Description
  503.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  504.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  505.     dpAppDesc.guidApplication = g_guidApp;
  506.     dpAppDesc.pwszSessionName = wszSession;
  507.  
  508.     // We are now ready to host the app
  509.     if( FAILED( hr = g_pDP->Host( &dpAppDesc,             // AppDesc
  510.                                   &g_pDeviceAddress, 1,   // Device Address
  511.                                   NULL, NULL,             // Reserved
  512.                                   NULL,                   // Player Context
  513.                                   0 ) ) )                 // dwFlags
  514.     {
  515.         printf("Failed Hosting:  0x%X\n", hr);
  516.         goto LCleanup;
  517.     }
  518.     else
  519.     {
  520.         printf("Currently Hosting...\n");
  521.     }
  522.  
  523.  
  524. LCleanup:
  525.     return hr;
  526. }
  527.  
  528.  
  529.  
  530.  
  531. //-----------------------------------------------------------------------------
  532. // Name: ConnectToSession()
  533. // Desc: Connects to a DirectPlay session
  534. //-----------------------------------------------------------------------------
  535. HRESULT ConnectToSession()
  536. {
  537.     HRESULT                     hr = E_FAIL;
  538.     DPN_APPLICATION_DESC        dpnAppDesc;
  539.     IDirectPlay8Address*        pHostAddress = NULL;
  540.  
  541.  
  542.     ZeroMemory(&dpnAppDesc, sizeof(DPN_APPLICATION_DESC));
  543.     dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  544.     dpnAppDesc.guidApplication = g_guidApp;
  545.  
  546.  
  547.     // Simply connect to the first one in the list
  548.     EnterCriticalSection(&g_csHostList);
  549.  
  550.     if( g_pHostList && SUCCEEDED(hr = g_pHostList->pHostAddress->Duplicate(&pHostAddress ) ) )
  551.     {
  552.         hr = g_pDP->Connect( &dpnAppDesc,        // pdnAppDesc
  553.                              pHostAddress,       // pHostAddr
  554.                              g_pDeviceAddress,   // pDeviceInfo
  555.                              NULL,               // pdnSecurity
  556.                              NULL,               // pdnCredentials
  557.                              NULL, 0,            // pvUserConnectData/Size
  558.                              NULL,               // pvPlayerContext
  559.                              NULL,               // pvAsyncContext
  560.                              NULL,               // pvAsyncHandle
  561.                              DPNCONNECT_SYNC);   // dwFlags
  562.  
  563.         if( FAILED( hr))
  564.             printf("Failed Connecting to Host:  0x%x\n", hr);
  565.     }
  566.     else
  567.     {
  568.         printf("Failed Duplicating Host Address:  0x%x\n", hr);
  569.     }
  570.  
  571.     LeaveCriticalSection(&g_csHostList);
  572.  
  573.     SAFE_RELEASE(pHostAddress);
  574.     return hr;
  575. }
  576.  
  577.  
  578.  
  579.  
  580. //-----------------------------------------------------------------------------
  581. // Name: SendDirectPlayMessage()
  582. // Desc: Sends a DirectPlay message to all players
  583. //-----------------------------------------------------------------------------
  584. HRESULT SendDirectPlayMessage()
  585. {
  586.     HRESULT         hr = S_OK;
  587.     DPN_BUFFER_DESC dpnBuffer;
  588.     WCHAR           wszData[256];
  589.  
  590.     // Get the data from the user
  591.     printf("\nPlease Enter a String.\n");
  592.     wscanf(L"%ls", wszData);
  593.  
  594.     dpnBuffer.pBufferData = (BYTE*) wszData;
  595.     dpnBuffer.dwBufferSize = 2 * (wcslen(wszData) + 1);
  596.  
  597.     if( FAILED( hr = g_pDP->SendTo( DPNID_ALL_PLAYERS_GROUP, // dpnid
  598.                                     &dpnBuffer,             // pBufferDesc
  599.                                     1,                      // cBufferDesc
  600.                                     0,                      // dwTimeOut
  601.                                     NULL,                   // pvAsyncContext
  602.                                     NULL,                   // pvAsyncHandle
  603.                                     DPNSEND_SYNC |
  604.                                     DPNSEND_NOLOOPBACK ) ) )    // dwFlags
  605.     {
  606.         printf("Failed Sending Data:  0x%x\n", hr);
  607.     }
  608.  
  609.     return hr;
  610. }
  611.  
  612.  
  613.  
  614.  
  615. //-----------------------------------------------------------------------------
  616. // Name: CleanupDirectPlay()
  617. // Desc: Cleanup DirectPlay
  618. //-----------------------------------------------------------------------------
  619. void CleanupDirectPlay()
  620. {
  621.     HOST_NODE* pHostNode    = NULL;
  622.     HOST_NODE* pHostNodetmp = NULL;
  623.  
  624.     // Cleanup DirectPlay
  625.     if( g_pDP)
  626.         g_pDP->Close(0);
  627.  
  628.     // Clean up Host list
  629.     EnterCriticalSection(&g_csHostList);
  630.     
  631.     pHostNode = g_pHostList;
  632.     while( pHostNode != NULL )
  633.     {       
  634.         SAFE_RELEASE(pHostNode->pHostAddress);
  635.         SAFE_DELETE(pHostNode->pAppDesc);
  636.         SAFE_DELETE(pHostNode->pwszSessionName);
  637.  
  638.         pHostNodetmp = pHostNode;
  639.         pHostNode    = pHostNode->pNext;
  640.         SAFE_DELETE(pHostNodetmp);
  641.     }
  642.  
  643.     LeaveCriticalSection(&g_csHostList);
  644.  
  645.     SAFE_RELEASE(g_pDeviceAddress);
  646.     SAFE_RELEASE(g_pHostAddress);
  647.     SAFE_RELEASE(g_pDP);
  648.  
  649.     DeleteCriticalSection(&g_csHostList);
  650. }
  651.  
  652.